home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / General / GCC 1.37.1r15 / Machines / out-alliant.c < prev    next >
Text File  |  1990-03-14  |  9KB  |  292 lines

  1. /* Subroutines for insn-output.c for Alliant FX computers.
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. /* Some output-actions in alliant.md need these.  */
  22. #include <stdio.h>
  23. extern FILE *asm_out_file;
  24.  
  25. /* Index into this array by (register number >> 3) to find the
  26.    smallest class which contains that register.  */
  27. enum reg_class regno_reg_class[]
  28.   = { DATA_REGS, ADDR_REGS, FP_REGS };
  29.  
  30. static rtx find_addr_reg ();
  31.  
  32. char *
  33. output_btst (operands, countop, dataop, insn, signpos)
  34.      rtx *operands;
  35.      rtx countop, dataop;
  36.      rtx insn;
  37.      int signpos;
  38. {
  39.   operands[0] = countop;
  40.   operands[1] = dataop;
  41.  
  42.   if (GET_CODE (countop) == CONST_INT)
  43.     {
  44.       register int count = INTVAL (countop);
  45.       /* If COUNT is bigger than size of storage unit in use,
  46.      advance to the containing unit of same size.  */
  47.       if (count > signpos)
  48.     {
  49.       int offset = (count & ~signpos) / 8;
  50.       count = count & signpos;
  51.       operands[1] = dataop = adj_offsettable_operand (dataop, offset);
  52.     }
  53.       if (count == signpos)
  54.     cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
  55.       else
  56.     cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
  57.  
  58.       if (count == 31
  59.       && next_insns_test_no_inequality (insn))
  60.     return "tst%.l %1";
  61.       if (count == 15
  62.       && next_insns_test_no_inequality (insn))
  63.     return "tst%.w %1";
  64.       if (count == 7
  65.       && next_insns_test_no_inequality (insn))
  66.     return "tst%.b %1";
  67.  
  68.       cc_status.flags = CC_NOT_NEGATIVE;
  69.     }
  70.   return "btst %0,%1";
  71. }
  72.  
  73. /* Return the best assembler insn template
  74.    for moving operands[1] into operands[0] as a fullword.  */
  75.  
  76. static char *
  77. singlemove_string (operands)
  78.      rtx *operands;
  79. {
  80.   if (operands[1] != const0_rtx)
  81.     return "mov%.l %1,%0";
  82.   if (! ADDRESS_REG_P (operands[0]))
  83.     return "clr%.l %0";
  84.   return "sub%.l %0,%0";
  85. }
  86.  
  87. /* Output assembler code to perform a doubleword move insn
  88.    with operands OPERANDS.  */
  89.  
  90. char *
  91. output_move_double (operands)
  92.      rtx *operands;
  93. {
  94.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  95.   rtx latehalf[2];
  96.   rtx addreg0 = 0, addreg1 = 0;
  97.  
  98.   /* First classify both operands.  */
  99.  
  100.   if (REG_P (operands[0]))
  101.     optype0 = REGOP;
  102.   else if (offsettable_memref_p (operands[0]))
  103.     optype0 = OFFSOP;
  104.   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  105.     optype0 = POPOP;
  106.   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
  107.     optype0 = PUSHOP;
  108.   else if (GET_CODE (operands[0]) == MEM)
  109.     optype0 = MEMOP;
  110.   else
  111.     optype0 = RNDOP;
  112.  
  113.   if (REG_P (operands[1]))
  114.     optype1 = REGOP;
  115.   else if (CONSTANT_P (operands[1])
  116.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  117.     optype1 = CNSTOP;
  118.   else if (offsettable_memref_p (operands[1]))
  119.     optype1 = OFFSOP;
  120.   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  121.     optype1 = POPOP;
  122.   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
  123.     optype1 = PUSHOP;
  124.   else if (GET_CODE (operands[1]) == MEM)
  125.     optype1 = MEMOP;
  126.   else
  127.     optype1 = RNDOP;
  128.  
  129.   /* Check for the cases that the operand constraints are not
  130.      supposed to allow to happen.  Abort if we get one,
  131.      because generating code for these cases is painful.  */
  132.  
  133.   if (optype0 == RNDOP || optype1 == RNDOP)
  134.     abort ();
  135.  
  136.   /* If one operand is decrementing and one is incrementing
  137.      decrement the former register explicitly
  138.      and change that operand into ordinary indexing.  */
  139.  
  140.   if (optype0 == PUSHOP && optype1 == POPOP)
  141.     {
  142.       operands[0] = XEXP (XEXP (operands[0], 0), 0);
  143.       output_asm_insn ("subq%.l %#8,%0", operands);
  144.       operands[0] = gen_rtx (MEM, DImode, operands[0]);
  145.       optype0 = OFFSOP;
  146.     }
  147.   if (optype0 == POPOP && optype1 == PUSHOP)
  148.     {
  149.       operands[1] = XEXP (XEXP (operands[1], 0), 0);
  150.       output_asm_insn ("subq%.l %#8,%1", operands);
  151.       operands[1] = gen_rtx (MEM, DImode, operands[1]);
  152.       optype1 = OFFSOP;
  153.     }
  154.  
  155.   /* If an operand is an unoffsettable memory ref, find a register
  156.      we can increment temporarily to make it refer to the second word.  */
  157.  
  158.   if (optype0 == MEMOP)
  159.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  160.  
  161.   if (optype1 == MEMOP)
  162.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  163.  
  164.   /* Ok, we can do one word at a time.
  165.      Normally we do the low-numbered word first,
  166.      but if either operand is autodecrementing then we
  167.      do the high-numbered word first.
  168.  
  169.      In either case, set up in LATEHALF the operands to use
  170.      for the high-numbered word and in some cases alter the
  171.      operands in OPERANDS to be suitable for the low-numbered word.  */
  172.  
  173.   if (optype0 == REGOP)
  174.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  175.   else if (optype0 == OFFSOP)
  176.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  177.   else
  178.     latehalf[0] = operands[0];
  179.  
  180.   if (optype1 == REGOP)
  181.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  182.   else if (optype1 == OFFSOP)
  183.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  184.   else if (optype1 == CNSTOP)
  185.     {
  186.       if (CONSTANT_P (operands[1]))
  187.     latehalf[1] = const0_rtx;
  188.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  189.     {
  190.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  191.                  CONST_DOUBLE_HIGH (operands[1]));
  192.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  193.                  CONST_DOUBLE_LOW (operands[1]));
  194.     }
  195.     }
  196.   else
  197.     latehalf[1] = operands[1];
  198.  
  199.   /* If insn is effectively movd N(sp),-(sp) then we will do the
  200.      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
  201.      for the low word as well, to compensate for the first decrement of sp.  */
  202.   if (optype0 == PUSHOP
  203.       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
  204.       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
  205.     operands[1] = latehalf[1];
  206.  
  207.   /* If one or both operands autodecrementing,
  208.      do the two words, high-numbered first.  */
  209.  
  210.   /* Likewise,  the first move would clobber the source of the second one,
  211.      do them in the other order.  This happens only for registers;
  212.      such overlap can't happen in memory unless the user explicitly
  213.      sets it up, and that is an undefined circumstance.  */
  214.  
  215.   if (optype0 == PUSHOP || optype1 == PUSHOP
  216.       || (optype0 == REGOP && optype1 == REGOP
  217.       && REGNO (operands[0]) == REGNO (latehalf[1])))
  218.     {
  219.       /* Make any unoffsettable addresses point at high-numbered word.  */
  220.       if (addreg0)
  221.     output_asm_insn ("addql %#4,%0", &addreg0);
  222.       if (addreg1)
  223.     output_asm_insn ("addql %#4,%0", &addreg1);
  224.  
  225.       /* Do that word.  */
  226.       output_asm_insn (singlemove_string (latehalf), latehalf);
  227.  
  228.       /* Undo the adds we just did.  */
  229.       if (addreg0)
  230.     output_asm_insn ("subql %#4,%0", &addreg0);
  231.       if (addreg1)
  232.     output_asm_insn ("subql %#4,%0", &addreg1);
  233.  
  234.       /* Do low-numbered word.  */
  235.       return singlemove_string (operands);
  236.     }
  237.  
  238.   /* Normal case: do the two words, low-numbered first.  */
  239.  
  240.   output_asm_insn (singlemove_string (operands), operands);
  241.  
  242.   /* Make any unoffsettable addresses point at high-numbered word.  */
  243.   if (addreg0)
  244.     output_asm_insn ("addql %#4,%0", &addreg0);
  245.   if (addreg1)
  246.     output_asm_insn ("addql %#4,%0", &addreg1);
  247.  
  248.   /* Do that word.  */
  249.   output_asm_insn (singlemove_string (latehalf), latehalf);
  250.  
  251.   /* Undo the adds we just did.  */
  252.   if (addreg0)
  253.     output_asm_insn ("subql %#4,%0", &addreg0);
  254.   if (addreg1)
  255.     output_asm_insn ("subql %#4,%0", &addreg1);
  256.  
  257.   return "";
  258. }
  259.  
  260. /* Return a REG that occurs in ADDR with coefficient 1.
  261.    ADDR can be effectively incremented by incrementing REG.  */
  262.  
  263. static rtx
  264. find_addr_reg (addr)
  265.      rtx addr;
  266. {
  267.   while (GET_CODE (addr) == PLUS)
  268.     {
  269.       if (GET_CODE (XEXP (addr, 0)) == REG)
  270.     addr = XEXP (addr, 0);
  271.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  272.     addr = XEXP (addr, 1);
  273.       else if (CONSTANT_P (XEXP (addr, 0)))
  274.     addr = XEXP (addr, 1);
  275.       else if (CONSTANT_P (XEXP (addr, 1)))
  276.     addr = XEXP (addr, 0);
  277.       else
  278.     abort ();
  279.     }
  280.   if (GET_CODE (addr) == REG)
  281.     return addr;
  282.   abort ();
  283. }
  284.  
  285. int
  286. standard_SunFPA_constant_p (x)
  287.      rtx x;
  288. {
  289.   return( 0 );
  290. }
  291.  
  292.